﻿
using Xacml.Core.Policy;
using System;
using System.IO;
using System.Xml;

namespace Xacml.Core
{
  public sealed class PolicyLoader
  {
    private PolicyLoader()
    {
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(string xmlDocument, DocumentAccess access)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      XacmlVersion xacmlVersion = PolicyLoader.GetXacmlVersion((TextReader) new StreamReader(xmlDocument));
      return PolicyLoader.LoadPolicyDocument((TextReader) new StringReader(xmlDocument), xacmlVersion, access);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(Stream xmlDocument, DocumentAccess access)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      if (!xmlDocument.CanSeek)
        throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_stream_parameter_canseek], "xmlDocument");
      XacmlVersion xacmlVersion = PolicyLoader.GetXacmlVersion((TextReader) new StreamReader(xmlDocument));
      xmlDocument.Position = 0L;
      return PolicyLoader.LoadPolicyDocument((TextReader) new StreamReader(xmlDocument), xacmlVersion, access);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(Stream xmlDocument, XacmlVersion version, DocumentAccess access)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      return PolicyLoader.LoadPolicyDocument((TextReader) new StreamReader(xmlDocument), version, access);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(TextReader xmlDocument, XacmlVersion version, DocumentAccess access)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      return PolicyLoader.LoadPolicyDocument((XmlReader) new XmlTextReader(xmlDocument), version, access);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(XmlReader reader, XacmlVersion version, DocumentAccess access)
    {
      if (reader == null)
        throw new ArgumentNullException("reader");
      if (access.Equals((object) DocumentAccess.ReadOnly))
        return (PolicyDocumentReadWrite) new PolicyDocument(reader, version);
      if (access.Equals((object) DocumentAccess.ReadWrite))
        return new PolicyDocumentReadWrite(reader, version);
      return (PolicyDocumentReadWrite) null;
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(string xmlDocument)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      XacmlVersion xacmlVersion = PolicyLoader.GetXacmlVersion((TextReader) new StreamReader(xmlDocument));
      return PolicyLoader.LoadPolicyDocument((TextReader) new StringReader(xmlDocument), xacmlVersion);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(Stream xmlDocument)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      if (!xmlDocument.CanSeek)
        throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_stream_parameter_canseek], "xmlDocument");
      XacmlVersion xacmlVersion = PolicyLoader.GetXacmlVersion((TextReader) new StreamReader(xmlDocument));
      xmlDocument.Position = 0L;
      return PolicyLoader.LoadPolicyDocument((TextReader) new StreamReader(xmlDocument), xacmlVersion);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(Stream xmlDocument, XacmlVersion version)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      return PolicyLoader.LoadPolicyDocument((TextReader) new StreamReader(xmlDocument), version);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(TextReader xmlDocument, XacmlVersion version)
    {
      if (xmlDocument == null)
        throw new ArgumentNullException("xmlDocument");
      return PolicyLoader.LoadPolicyDocument((XmlReader) new XmlTextReader(xmlDocument), version);
    }

    public static PolicyDocumentReadWrite LoadPolicyDocument(XmlReader reader, XacmlVersion version)
    {
      if (reader == null)
        throw new ArgumentNullException("reader");
      return (PolicyDocumentReadWrite) new PolicyDocument(reader, version);
    }

    private static XacmlVersion GetXacmlVersion(TextReader textReader)
    {
      XmlTextReader xmlTextReader = new XmlTextReader(textReader);
      while (xmlTextReader.Read())
      {
        if (xmlTextReader.LocalName == "PolicySet" || xmlTextReader.LocalName == "Policy")
        {
          if (xmlTextReader.NamespaceURI == "urn:oasis:names:tc:xacml:1.0:policy")
            return XacmlVersion.Version11;
          if (xmlTextReader.NamespaceURI == "urn:oasis:names:tc:xacml:2.0:policy")
            return XacmlVersion.Version20;
        }
      }
      throw new Exception(Resource.ResourceManager[Resource.MessageKey.exc_invalid_document_format_no_policyorpolicyset]);
    }
  }
}
